package com.bcx.wind.workflow.imp.cmd.corecmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.OrderStatus;
import com.bcx.wind.workflow.core.constant.TaskLevel;
import com.bcx.wind.workflow.core.constant.TaskStatus;
import com.bcx.wind.workflow.core.constant.WorkflowOperate;
import com.bcx.wind.workflow.core.flow.NodeModel;
import com.bcx.wind.workflow.core.flow.node.TaskNode;
import com.bcx.wind.workflow.entity.WindOrder;
import com.bcx.wind.workflow.entity.WindProcess;
import com.bcx.wind.workflow.entity.WindProcessConfig;
import com.bcx.wind.workflow.entity.WindTask;
import com.bcx.wind.workflow.interceptor.Context;
import com.bcx.wind.workflow.pojo.Task;
import com.bcx.wind.workflow.pojo.Wind;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.pojo.variable.RejectVariable;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.ObjectHelper;

import java.util.Collections;
import java.util.List;

import static com.bcx.wind.workflow.access.AccessSqlConstant.DESC;
import static com.bcx.wind.workflow.access.AccessSqlConstant.ORDER_ID;
import static com.bcx.wind.workflow.core.constant.Constant.WIND_ADMIN;
import static com.bcx.wind.workflow.message.ErrorCode.*;

public class RejectCommand extends BaseCommand {

    /**
     * 退回参数
     */
    private RejectVariable variable;

    private List<WindTask> curTasks;


    public RejectCommand(RejectVariable variable){
        this.variable = variable;
    }

    @Override
    public Wind execute() {
        //操作
        wind().setOperate(WorkflowOperate.reject);
        //校验参数
        checkVariable();
        //构建wind
        initWind();
        //构建当前节点
        initCurTask();
        //执行
        exec();
        return wind();
    }


    private void exec(){
        for(WindTask windTask : this.curTasks){
            Task task = buildCurNodeConfig(windTask.getTaskName(),windTask);
            wind().getCurNode().add(task);
            //添加撤销记录
            addRevokeData(windTask);
            //执行
            NodeModel nodeModel = task.getTaskNode();
            //校验当前节点是否可以驳回
            if(nodeModel instanceof TaskNode) {
                Assert.isTrueError(TASK_CAN_NOT_REJECT, ((TaskNode) nodeModel).inForkJoin());
            }
            nodeModel.context(this.commandContext,task);
            nodeModel.execute();

            //删除本地数据
            Context.remove();
        }
    }


    private  void  initCurTask(){
        String userId = wind().getUser().getUserId();
        WindOrder order = wind().getWindOrder();

        QueryFilter filter = new QueryFilter()
                .setOrderId(wind().getWindOrder().getId())
                .setStatus(TaskStatus.run.name())
                .setTaskLevel(TaskLevel.main.name());
        if(order.getVersion() > 1){
            filter.setTaskActorId(new String[]{userId});
            if(!ObjectHelper.isEmpty(this.variable.getTaskId())){
                filter.setTaskId(variable.getTaskId());
            }
        }
        //时间排序
        filter.setOrderBy(DESC);
        List<WindTask> tasks = this.commandContext.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(NOT_FOUND_TASK,tasks);
        //默认执行先执行自己的第一个任务
        this.curTasks = Collections.singletonList(tasks.get(0));
    }



    private void checkVariable(){
        Assert.notEmptyError(REJECT_NOT_FOUND_ARGS,variable);
        String orderId = this.variable.getOrderId();
        Assert.notEmptyError(REJECT_FAIL,orderId,ORDER_ID);
    }


    private void initWind(){
        //流程实例
        String orderId = this.variable.getOrderId();
        WindOrder windOrder = buildWindOrder(orderId);

        //流程实例下所有任务
        QueryFilter filter = new QueryFilter()
                .setOrderId(orderId);
        List<WindTask> allTasks = this.commandContext.access().selectTaskInstanceList(filter);

        //流程定义
        WindProcess windProcess = this.commandContext.repositoryService().queryById(windOrder.getProcessId());
        Assert.notEmptyError(PROCESS_QUERY_NULL,windProcess,windOrder.getProcessId());

        //所有配置
        getConfigList(windProcess.getId());

        wind().setWindOrder(windOrder)
                .setBusinessId(windOrder.getBusinessId())
                .setAllTasks(allTasks)
                .setOperator(user().getUserId())
                .setSuggest(variable.getSuggest())
                .setSubmitNode(variable.getReturnNode())
                .setSystem(variable.getSystem())
                .setUser(user())
                .setWindProcess(windProcess)
                .setWindConfig(buildWindConfig(buildProcessConfig()));
        if(variable.getVars() != null){
            this.wind().setVars(this.variable.getVars());
        }
        if(variable.getArgs() != null){
            this.wind().setArgs(this.variable.getArgs());
        }
    }


    /**
     * 当前流程配置
     */
    private WindProcessConfig  buildProcessConfig(){
        String processName = wind().getWindProcess().getProcessName();
        WindProcessConfig processConfig = ObjectHelper.getNodeConfig(this.configList,processName,this.variable.getArgs());
        Assert.notEmptyError(PROCESS_CONFIG_NOT_FOUND,processConfig,processName,processName);
        return processConfig;
    }



    /**
     * 当前用户  默认使用 wind_admin
     * @return  当前用户
     */
    private WindUser  user(){
        WindUser user = this.variable.getUser();
        if(user == null){
            user = new WindUser()
                    .setUserId(WIND_ADMIN)
                    .setUserName("管理员");
        }
        return user;
    }
}